#!/usr/bin/env python
#
#       MajeRe_Engine.py
#       
#       Copyright 2009 Brandon Invergo <brandon@brandoninvergo.com>
#       
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#       
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#       
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

from rpy2 import robjects
from rpy2 import rinterface

class MajeRe_Engine:
    
    out_buf = []
    
    def __init__(self):
        robjects.rinterface.setWriteConsole(self.write_console)
        return
    
    def write_console(self, output):
        self.out_buf.append(output)
    
    def buf2linebuf(self, buf):
        line = ""
        line_buf = []
        for cell in buf:
            if cell[0] == '\n':
                line_buf.append(line)
                line = cell#.lstrip()
            else:
                line = line + cell
        line_buf.append(line)
        return line_buf
        
    def clear_buf(self):
        self.out_buf = []
    
    def R(self, command):
        """This function handles R commands issued by the user or by plugins"""
        try:
            robjects.r["print"](robjects.r(command))
        except rinterface.RRuntimeError, RError:
            res_lines = self.buf2linebuf(self.out_buf)
            self.clear_buf()
            return [False, res_lines]
        else:
            res_lines = self.buf2linebuf(self.out_buf)
            self.clear_buf()
            return [True, res_lines]
        
    def get_objects(self):
        """This function returns a list of all R objects in memory.
        This needs to be improved to only include data objects (not 
        functions and such)."""
        objs = robjects.r("ls()")
        objs_str = [str(o) for o in objs]
        return set(objs_str)
        
    def get_length(self, obj):
        """This function returns the length of an object"""
        return robjects.r('length(%s)'%obj)[0]
        
    def delete_object(self, obj):
        """This function deletes an object by name"""
        try:
            robjects.r("rm(%s)"%obj)
        except:
            return False
        else:
            return True
    
    def get_type(self, obj):
        """This function returns the data type of an object"""
        try:
            res = robjects.r("typeof(%s)"%obj)
            res = str(res[0])
        except:
            return False
        else:
            return res
            
    def get_dataframe_names(self, dataframe):
        try:
            names = robjects.r("names(%s)"%dataframe)
        except rinterface.RRuntimeError, RError:
            RError = str(RError)
            RError = RError.partition(":")
            return "Error:" + RError[2]
        else:
            names_str = [dataframe + "$" + str(n) for n in names]
            return names_str
            
    def is_data_frame(self, obj):
        try: 
            res = robjects.r("is.data.frame(%s)"%obj)
        except:
            return False
        return res[0]
